home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / GlueWindow4.1.2(source) Folder / Source(THINK C7.0) / GlueWindowINIT4.1.2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  33.6 KB  |  1,168 lines  |  [TEXT/KAHL]

  1. //    GlueWindowINIT4.1.2.c
  2.  
  3. //    inclusion of files ------------------------------
  4.  
  5. #include    <SetUpA4.h>                //    To use globals in INIT.
  6. #include    <OSUtils.h>                //    To check whether Gestalt is available or not.
  7. #include    <Sound.h>                //    To use sound resources.
  8. #include    "GlueWindow4.1.2.h"        //    Inclusion of definition.
  9.  
  10. //    definition --------------------------------------
  11.  
  12. #define        key1        (**setting_hdl).push_key
  13. #define        key2        (**setting_hdl).pop_key
  14. #define        key3        (**setting_hdl).drag_key
  15.     //
  16.     //    #define        menu_bar_height        20
  17.     //    #define        gray_rect            my_qd_globals.screenBits.bounds
  18.     //
  19.     //    This definition is for GlueWindow4.1.1.
  20.     //    Not works properly with multi scan monitors.
  21.     //
  22. #define        gray_rect    (**GrayRgn).rgnBBox
  23. #define        PUSH_RSRC    0
  24. #define        POP_RSRC    1
  25. #define        menu_bar_height        0
  26.  
  27. //    declaration of prototypes -----------------------
  28.  
  29. int abs(int i);
  30.  
  31. pascal Boolean    (*TrackGoAwayProc)    (WindowPtr wp, Point mp);
  32. pascal void     (*DragWindowProc)    (WindowPtr wp, Point mp, Rect *r);
  33. pascal long     (*GrowWindowProc)    (WindowPtr wp, Point mp, Rect *r);
  34.  
  35. pascal void call_push_window(WindowPtr wp, Point mp, Rect *r);
  36. pascal void call_pop_window (WindowPtr wp, Point mp, Rect *r);
  37.  
  38. pascal Boolean call_original_go_away(WindowPtr wp, Point mp);
  39. pascal Boolean call_custom_go_away    (WindowPtr wp, Point mp);
  40. pascal Boolean my_track_go_away        (WindowPtr wp, Point mp);
  41.  
  42.  
  43. pascal void call_no_marquee_drag(WindowPtr wp, Point mp, Rect *r);
  44. pascal void call_original_drag    (WindowPtr wp, Point mp, Rect *r);
  45. pascal void call_custom_drag    (WindowPtr wp, Point mp, Rect *r);
  46. pascal void my_drag_window        (WindowPtr wp, Point mp, Rect *r);
  47.  
  48. pascal long call_original_grow    (WindowPtr wp, Point mp, Rect *r);
  49. pascal long call_custom_grow    (WindowPtr wp, Point mp, Rect *r);
  50. pascal long my_grow_window        (WindowPtr wp, Point mp, Rect *r);
  51.  
  52. void    draw_marquee(Rect *marquee, Rect *gap);
  53. void    copy_pattern(Pattern src_pat, Pattern dst_pat);
  54.  
  55.  
  56. pascal Handle    Get1Resource_in_system_heap(OSType rType, short id);
  57. pascal OSErr    my_gestalt_selector(OSType selector, long *responce);
  58. void            set_my_selector(ProcPtr func_address);
  59.  
  60. short        NumToolboxTraps( void );
  61. TrapType    GetTrapType(short theTrap);
  62. Boolean        TrapAvailable(short theTrap);
  63.  
  64. init_data_hdl    load_setting(void);
  65. void            save_setting(init_data_hdl sysheap_data_hdl, prefs_file *pf);
  66. int                open_prefs_file(prefs_file *pf);
  67. void            show_loading_icon(short which_icon);
  68. void            do_loading(void);
  69. Boolean            is_system7(void);
  70.  
  71. void main(void);
  72.  
  73. //    declaration of globals --------------------------
  74.  
  75. qd_globals        my_qd_globals;
  76. init_data_hdl    setting_hdl = nil;
  77. Handle            my_push_snd_hdl = nil;
  78. Handle            my_pop_snd_hdl = nil;
  79.  
  80. // main routines -----------------------------------
  81.  
  82. void main(void)
  83. {
  84.     RememberA0();    //    RememberA0(), SetUpA4() and RestoreA4() are keywords 
  85.     SetUpA4();        //    to use globals in code resources with THINK C.
  86.     
  87.     if(is_system7()) {
  88.         InitGraf(&my_qd_globals.thePort);                                                //    This initialization is to show the startup icon.
  89.         do_loading();
  90.     }
  91.     RestoreA4();
  92. }
  93.  
  94. Boolean is_system7(void)
  95. {
  96.     Boolean    f;
  97.     OSErr    err;
  98.     long    r;
  99.     
  100.     if(f = TrapAvailable(_Gestalt)) {
  101.             //    You have to check like this before using Gestalt.
  102.         err = Gestalt(gestaltSystemVersion, &r);
  103.         if(err != noErr)    f = false;
  104.         else if(r <0x0700) f = false;
  105.         else f = true;
  106.     }
  107.     return(f);
  108. }
  109.  
  110. void do_loading(void)
  111. {
  112.     short        icon_number = SHOW_OK_ICON;
  113.     Handle        h;
  114.     Rect        r;
  115.     long        drag_address, grow_address, away_address;
  116.     ProcPtr        selector_func_address;
  117.     
  118.     h = Get1Resource_in_system_heap('INIT', RSRC_NUMBER_BASE);
  119.     if(h) {
  120.         setting_hdl = load_setting();
  121.         if(setting_hdl) {
  122.             DetachResource(h);    //    If you don't detach, 
  123.             HLock(h);            //    resources are purged at the end of INIT.
  124.             HNoPurge(h);
  125.             
  126.             //    You can use 'trapped' system routines with following procedures. 
  127.             
  128.             away_address = NGetTrapAddress(_TrackGoAway, ToolTrap);
  129.             drag_address = NGetTrapAddress(_DragWindow, ToolTrap);
  130.             grow_address = NGetTrapAddress(_GrowWindow, ToolTrap);
  131.             
  132.             TrackGoAwayProc = (pascal Boolean (*)(WindowPtr, Point))away_address;
  133.             DragWindowProc = (pascal void (*)(WindowPtr, Point, Rect*))drag_address;
  134.             GrowWindowProc = (pascal long (*)(WindowPtr, Point, Rect*))grow_address;
  135.             
  136.             NSetTrapAddress((long) my_track_go_away, _TrackGoAway, ToolTrap);
  137.             NSetTrapAddress((long) my_drag_window, _DragWindow, ToolTrap);
  138.             NSetTrapAddress((long) my_grow_window, _GrowWindow, ToolTrap);
  139.             
  140.             if(TrapAvailable(_SndPlay)) {    //    To use sound routines, you must check.
  141.                 my_push_snd_hdl = Get1Resource_in_system_heap('snd ',
  142.                                                 RSRC_NUMBER_BASE + PUSH_RSRC);
  143.                 if(my_push_snd_hdl) {
  144.                     DetachResource(my_push_snd_hdl);
  145.                     HLock(my_push_snd_hdl);
  146.                     HNoPurge(my_push_snd_hdl);
  147.                     my_pop_snd_hdl = Get1Resource_in_system_heap('snd ',
  148.                                                 RSRC_NUMBER_BASE + POP_RSRC);
  149.                     if(my_pop_snd_hdl) {
  150.                         DetachResource(my_pop_snd_hdl);
  151.                         HLock(my_pop_snd_hdl);
  152.                         HNoPurge(my_pop_snd_hdl);
  153.                     }
  154.                 }
  155.             }
  156.             selector_func_address = (ProcPtr)my_gestalt_selector; 
  157.             set_my_selector(selector_func_address);
  158.             if(!(**setting_hdl).show_init_icon) {
  159.                 icon_number = SHOW_NO_ICON;
  160.             }
  161.         } 
  162.         else {
  163.             icon_number = SHOW_NG_ICON;
  164.             ReleaseResource(h);
  165.                 //    If loading is failed, the 'INIT' resource is released.
  166.         }
  167.     } else        icon_number = SHOW_NG_ICON;
  168.     show_loading_icon(icon_number);
  169. }
  170.  
  171. void show_loading_icon(short which_icon)
  172. {
  173.     Handle        icon_h = nil;
  174.     GrafPtr        saved_port;
  175.     GrafPort    temp_port;
  176.     Rect        r;
  177.     short        screen_width;
  178.     Boolean        color_icon;
  179.  
  180.     if(which_icon != SHOW_NO_ICON) {
  181.         color_icon = TrapAvailable(_GetCIcon);
  182.             //    Sometimes you can't use 'cicn' color icon resources
  183.             //    because GetCIcon and PlotCIcon are not implemented.    
  184.         if(color_icon)
  185.             icon_h = (Handle)GetCIcon(RSRC_NUMBER_BASE + which_icon);
  186.         else
  187.             icon_h = GetIcon(RSRC_NUMBER_BASE + which_icon);
  188.         if(icon_h) {
  189.             HNoPurge(icon_h);
  190.             GetPort(&saved_port);
  191.             OpenPort(&temp_port);
  192.             SetPort(&temp_port);
  193.             if(((icon_loc_h << 1) ^ 0x1021) != icon_loc_cs) icon_loc_h = 8;
  194.             screen_width =  ((temp_port.portRect.right    -
  195.                               temp_port.portRect.left)    / 40) * 40;
  196.             r.left    = icon_loc_h % screen_width;
  197.             r.right    = r.left + 32;
  198.             r.top    = temp_port.portRect.bottom -
  199.                         (40 * (1 + icon_loc_h / screen_width));
  200.             r.bottom = r.top + 32;
  201.             if(color_icon)
  202.                 PlotCIcon(&r, (CIconHandle)icon_h);
  203.             else
  204.                 PlotIcon(&r, icon_h);
  205.             icon_loc_h += 40;
  206.             icon_loc_cs = (icon_loc_h<<1) ^ 0x1021;
  207.             if(color_icon)
  208.                 DisposeCIcon((CIconHandle)icon_h);
  209.             else
  210.                 DisposeHandle(icon_h);
  211.             SetPort(saved_port);
  212.             ClosePort(&temp_port);
  213.         }
  214.     }
  215. }
  216.  
  217. //    gestalt check routines ----------------------------------
  218.  
  219. #define TrapMask 0x0800
  220.  
  221. short NumToolboxTraps( void )
  222. {
  223.     if (NGetTrapAddress(_InitGraf, ToolTrap) ==
  224.             NGetTrapAddress(0xAA6E, ToolTrap))
  225.         return(0x0200);
  226.     else
  227.         return(0x0400);
  228. }
  229.  
  230. TrapType GetTrapType(short theTrap)
  231. {
  232.  
  233.     if ((theTrap & TrapMask) > 0)
  234.         return(ToolTrap);
  235.     else
  236.         return(OSTrap);
  237.  
  238. }
  239.  
  240. Boolean TrapAvailable(short theTrap)
  241. {
  242.  
  243.     TrapType    tType;
  244.  
  245.     tType = GetTrapType(theTrap);
  246.     if (tType == ToolTrap)
  247.     theTrap = theTrap & 0x07FF;
  248.     if (theTrap >= NumToolboxTraps())
  249.         theTrap = _Unimplemented;
  250.  
  251.     return (NGetTrapAddress(theTrap, tType) !=
  252.             NGetTrapAddress(_Unimplemented, ToolTrap));
  253. }
  254.  
  255. //    setting gestalt routines -------------------------
  256.  
  257. void set_my_selector(ProcPtr func_address)
  258. {
  259.     OSErr    er;
  260.     
  261.     if(TrapAvailable(_Gestalt)) {
  262.         SetUpA4();
  263.         er = NewGestalt(CREATOR, func_address);
  264.             //    To hand address of INIT globals to cdev, you can use NewGestalt.
  265.         RestoreA4();
  266.     }
  267. }
  268.  
  269. pascal OSErr my_gestalt_selector(OSType selector, long *responce)
  270. {
  271.     SetUpA4();
  272.     *responce = (long)setting_hdl;
  273.     RestoreA4();    //    All you have to do is wriiten here.
  274.     return(NO_ERROR);
  275. }
  276.  
  277. pascal Handle Get1Resource_in_system_heap(OSType rType, short id)
  278. {
  279.     THz        oldZone;
  280.     Handle    h;
  281.  
  282.     oldZone = GetZone();
  283.     SetZone(SystemZone());
  284.     h = Get1Resource(rType, id);
  285.     SetZone(oldZone);
  286.     return(h);
  287. }
  288.  
  289. //    data routines -----------------------------------
  290.  
  291. init_data_hdl load_setting(void)
  292. {
  293.     init_data_hdl        h = nil, work_h = nil;
  294.     old_init_data_hdl    old_h;
  295.     prefs_file            pf;
  296.     int                    er;
  297.     short                saved_ref_num;
  298.     
  299.     saved_ref_num = CurResFile();
  300.     er = open_prefs_file(&pf);
  301.         //    pf is struct which contains all parameters to use preferences file.
  302.     if(er == NO_ERROR) {
  303.         h = (init_data_hdl)Get1Resource_in_system_heap(SETTING_RSRC, RSRC_NUMBER_BASE + 1);
  304.         if(h) {
  305.             HNoPurge((Handle)h);
  306.             DetachResource((Handle)h);
  307.         }
  308.         else {
  309.             old_h = (old_init_data_hdl)Get1Resource(SETTING_RSRC, RSRC_NUMBER_BASE);
  310.             if(old_h) {
  311.                 h = (init_data_hdl)NewHandleSys(sizeof(init_data));
  312.                 if(h) {
  313.                     (**h).drag_on        = (**old_h).drag_on;
  314.                     (**h).grow_on        = (**old_h).grow_on;
  315.                     (**h).push_on        = (**old_h).push_on;
  316.                     (**h).pop_on        = (**old_h).pop_on;
  317.                     (**h).push_sound    = (**old_h).push_sound;
  318.                     (**h).pop_sound        = (**old_h).pop_sound;
  319.                     (**h).push_key[0]    = (**old_h).push_key[0];
  320.                     (**h).push_key[1]    = (**old_h).push_key[1];
  321.                     (**h).push_key[2]    = (**old_h).push_key[2];
  322.                     (**h).push_key[3]    = (**old_h).push_key[3];
  323.                     (**h).pop_key[0]    = (**old_h).pop_key[0];
  324.                     (**h).pop_key[1]    = (**old_h).pop_key[1];
  325.                     (**h).pop_key[2]    = (**old_h).pop_key[2];
  326.                     (**h).pop_key[3]    = (**old_h).pop_key[3];
  327.                     (**h).show_init_icon= (**old_h).show_init_icon;
  328.                     (**h).no_marquee    = false;
  329.                     (**h).drag_key[0]    = false;
  330.                     (**h).drag_key[1]    = false;
  331.                     (**h).drag_key[2]    = false;
  332.                     (**h).drag_key[3]    = true;
  333.                     ReleaseResource((Handle)old_h);
  334.                     save_setting(h, &pf);
  335.                 }
  336.             }
  337.         }
  338.         CloseResFile(pf.RsrcRefNum);
  339.     }
  340.     else if(er == OPEN_ERROR) {
  341.         h = (init_data_hdl)NewHandleSys(sizeof(init_data));
  342.         if(h) {
  343.             (**h).drag_on        = true;
  344.             (**h).grow_on        = true;
  345.             (**h).push_on        = true;
  346.             (**h).pop_on        = true;
  347.             (**h).push_sound    = true;
  348.             (**h).pop_sound        = true;
  349.             (**h).push_key[0]    = false;
  350.             (**h).push_key[1]    = true;
  351.             (**h).push_key[2]    = false;
  352.             (**h).push_key[3]    = false;
  353.             (**h).pop_key[0]    = true;
  354.             (**h).pop_key[1]    = false;
  355.             (**h).pop_key[2]    = false;
  356.             (**h).pop_key[3]    = false;
  357.             (**h).show_init_icon= true;
  358.             (**h).no_marquee    = false;
  359.             (**h).drag_key[0]    = false;
  360.             (**h).drag_key[1]    = false;
  361.             (**h).drag_key[2]    = false;
  362.             (**h).drag_key[3]    = true;
  363.             save_setting(h, &pf);
  364.         }
  365.     }
  366.     UseResFile(saved_ref_num);
  367.     return(h);
  368. }
  369.  
  370. void save_setting(init_data_hdl sysheap_data_hdl, prefs_file *pf_ptr)
  371. {
  372.     Handle            h;
  373.     init_data_hdl    work_h;
  374.     OSErr            err;
  375.     FInfo            f_info;
  376.  
  377.     HCreateResFile(pf_ptr->vRefNum, pf_ptr->DirID, PREFS_TITLE);
  378.     f_info.fdType = 'pref';
  379.     f_info.fdCreator = CREATOR;
  380.     f_info.fdFlags = 0;
  381.     HSetFInfo(pf_ptr->vRefNum, pf_ptr->DirID, PREFS_TITLE, &f_info);
  382.     open_prefs_file(pf_ptr);    //    HSetFInfo close a resource file, so you must open again.
  383.  
  384.     work_h = (init_data_hdl)NewHandle(sizeof(init_data));
  385.     if(work_h) {
  386.         **work_h = **sysheap_data_hdl;
  387.         if(h = Get1Resource(SETTING_RSRC, RSRC_NUMBER_BASE + 1))
  388.             RmveResource(h);
  389.         AddResource((Handle)work_h, SETTING_RSRC, RSRC_NUMBER_BASE + 1, "\p");
  390.         ReleaseResource((Handle)work_h);
  391.         CloseResFile(pf_ptr->RsrcRefNum);
  392.     }
  393. }
  394.  
  395. int open_prefs_file(prefs_file *pf_ptr)
  396. {
  397.     OSErr        er;
  398.     int            rn;
  399.     
  400.     er = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
  401.                         &(pf_ptr->vRefNum), &(pf_ptr->DirID));
  402.     if(er == 0) {
  403.         rn = HOpenResFile(pf_ptr->vRefNum, pf_ptr->DirID, PREFS_TITLE, fsRdWrPerm);
  404.         if(rn != -1) {
  405.             pf_ptr->RsrcRefNum = rn;
  406.             return(NO_ERROR);
  407.         }
  408.         return(OPEN_ERROR);
  409.     }
  410.     return(CAUTION_ERROR);
  411. }
  412.  
  413. //    trap routines -----------------------------------
  414.  
  415. pascal Boolean my_track_go_away(WindowPtr wp, Point mp)
  416. {
  417.     KeyMap        my_keymap;
  418.     Boolean        f;
  419.     
  420.     SetUpA4();
  421.     GetKeys(my_keymap);
  422.     if(    (**setting_hdl).pop_on        &&
  423.         (key2[0] == BitTst(my_keymap, CONTROL_KEY))    &&
  424.         (key2[1] == BitTst(my_keymap, SHIFT_KEY))    &&
  425.         (key2[2] == BitTst(my_keymap, OPTION_KEY))    &&
  426.         (key2[3] == BitTst(my_keymap, COMMAND_KEY))    )
  427.             f = call_custom_go_away(wp, mp);
  428.     else    f = call_original_go_away(wp, mp);
  429.     RestoreA4();
  430.     return(f);
  431. }
  432.  
  433. pascal Boolean call_original_go_away(WindowPtr wp, Point mp)
  434. {
  435.     Boolean        f;
  436.  
  437.     f = (*TrackGoAwayProc)(wp, mp);
  438.     return(f);
  439. }
  440.  
  441. pascal Boolean call_custom_go_away(WindowPtr wp, Point mp)
  442. {
  443.     Boolean        f;
  444.     Point        pt;
  445.     GrafPtr        saved_port;
  446.     
  447.     f = call_original_go_away(wp, mp);
  448.     if(f) {
  449.         GetPort(&saved_port);
  450.         SetPort(wp);
  451.         MoveWindow(wp, std_state.left, std_state.top, false);
  452.         SetPort(saved_port);
  453.     }
  454.     if((**setting_hdl).pop_sound) {
  455.         if(TrapAvailable(_SndPlay) && my_pop_snd_hdl)
  456.             SndPlay(nil, my_pop_snd_hdl, false);
  457.         else SysBeep(1);
  458.     }
  459.     return(f);
  460. }
  461.  
  462. pascal void my_drag_window(WindowPtr wp, Point mp, Rect *r)
  463. {
  464.     KeyMap        my_keymap;
  465.     Rect        dummy_rect;
  466.     
  467.     SetUpA4();
  468.     GetKeys(my_keymap);
  469.     if(!setting_hdl)                    call_original_drag(wp, mp, r);
  470.     else if((**setting_hdl).no_marquee    &&
  471.             (key3[0] == BitTst(my_keymap, CONTROL_KEY))    &&
  472.             (key3[1] == BitTst(my_keymap, SHIFT_KEY))    &&
  473.             (key3[2] == BitTst(my_keymap, OPTION_KEY))    &&
  474.             (key3[3] == BitTst(my_keymap, COMMAND_KEY))    )
  475.                                         call_no_marquee_drag(wp, mp, r);
  476.     else if((**setting_hdl).push_on        &&
  477.             (key1[0] == BitTst(my_keymap, CONTROL_KEY))    &&
  478.             (key1[1] == BitTst(my_keymap, SHIFT_KEY))    &&
  479.             (key1[2] == BitTst(my_keymap, OPTION_KEY))    &&
  480.             (key1[3] == BitTst(my_keymap, COMMAND_KEY))    )
  481.                                         call_push_window(wp, mp, r);
  482.     else if((**setting_hdl).pop_on        &&
  483.             (key2[0] == BitTst(my_keymap, CONTROL_KEY))    &&
  484.             (key2[1] == BitTst(my_keymap, SHIFT_KEY))    &&
  485.             (key2[2] == BitTst(my_keymap, OPTION_KEY))    &&
  486.             (key2[3] == BitTst(my_keymap, COMMAND_KEY))    )
  487.                                         call_pop_window(wp, mp, r);
  488.     else if(!(**setting_hdl).drag_on)    call_original_drag(wp, mp, r);
  489.     else  call_custom_drag(wp, mp, r);
  490.     
  491.     if(!BitTst(my_keymap, COMMAND_KEY))
  492.             SelectWindow(wp);
  493.     
  494.     RestoreA4();
  495. }
  496.  
  497. pascal void call_original_drag(WindowPtr wp, Point mp, Rect *r)
  498. {
  499.     (*DragWindowProc)(wp, mp, r);
  500. }
  501.  
  502. pascal long my_grow_window(WindowPtr wp, Point mp, Rect *r)
  503. {
  504.     KeyMap        my_keymap;
  505.     long        v;
  506.     
  507.     SetUpA4();
  508.     GetKeys(my_keymap);
  509.  
  510.     if(!setting_hdl)
  511.         v = call_original_grow(wp, mp, r);
  512.     else if(!(**setting_hdl).grow_on)
  513.         v = call_original_grow(wp, mp, r);
  514.     else  v = call_custom_grow(wp, mp, r);
  515.     RestoreA4();
  516.     return(v);
  517. }
  518.  
  519. pascal long call_original_grow(WindowPtr wp, Point mp, Rect *r)
  520. {
  521.     long        v;
  522.     
  523.     v = (*GrowWindowProc)(wp, mp, r);
  524.     
  525.     return(v);
  526. }
  527.  
  528. pascal void call_push_window(WindowPtr wp, Point mp, Rect *r)
  529. {
  530.     GrafPtr            saved_port;
  531.     
  532.     GetPort(&saved_port);
  533.     SetPort(wp);
  534.     std_state.left    = (**((WindowPeek)wp)->contRgn).rgnBBox.left;
  535.     std_state.top    = (**((WindowPeek)wp)->contRgn).rgnBBox.top;
  536.     SetPort(saved_port);
  537.     if((**setting_hdl).push_sound) {
  538.         if(TrapAvailable(_SndPlay) && my_push_snd_hdl)
  539.             SndPlay(nil, my_push_snd_hdl, false);
  540.         else    SysBeep(1);
  541.     }
  542.     return;
  543. }
  544.  
  545. pascal void call_pop_window(WindowPtr wp, Point mp, Rect *r)
  546. {
  547.     GrafPtr        saved_port;
  548.  
  549.     GetPort(&saved_port);
  550.     SetPort(wp);
  551.     MoveWindow(wp, std_state.left, std_state.top, false);
  552.     SetPort(saved_port);
  553.     if((**setting_hdl).pop_sound) {
  554.         if(TrapAvailable(_SndPlay) && my_pop_snd_hdl)
  555.             SndPlay(nil, my_pop_snd_hdl, false);
  556.         else    SysBeep(1);
  557.     }
  558.     return;
  559. }
  560.     
  561.     
  562. pascal void    call_custom_drag(WindowPtr    wp,    Point mp, Rect *r)
  563. {
  564.     GrafPtr        saved_port;
  565.     Point        old_pt_g, new_pt_g, p, spread_l_to_g, saved_pt_g, mp_g,
  566.                 offset, w_g, saved_pn_size;
  567.     WindowPeek    wpk;
  568.     Boolean        h_changed, v_changed, color_qd;
  569.     Rect        wpk_rect_g, saved_rect_g, marquee_spread_l, c_rect_g, s_rect_g,
  570.                 gap, r_g, work_r;
  571.     short        c_width, c_height, screen_width, screen_height;
  572.     PenState    saved_pen_state;
  573.     char        i;
  574.     RgnHandle    new_rgn, saved_vis_rgn, saved_clip_rgn, s_rgn_g, marquee_rgn_spread_l;
  575.     RGBColor    fore_color, back_color;
  576.     PixPatHandle    saved_pn_pp_hdl, saved_fill_pp_hdl, saved_bk_pp_hdl,
  577.                     dummy_pn_pp_hdl, dummy_fill_pp_hdl, dummy_bk_pp_hdl;
  578.     Pattern        saved_bk_pat, saved_fill_pat, saved_pn_pat;
  579.     short        saved_pn_mode;
  580.     
  581.     
  582.     GetPort(&saved_port);
  583.  
  584.     if(color_qd = TrapAvailable(_GetForeColor)) {
  585.         GetForeColor(&fore_color);
  586.         GetBackColor(&back_color);
  587.         dummy_bk_pp_hdl = NewPixPat();
  588.         dummy_pn_pp_hdl = NewPixPat();
  589.         dummy_fill_pp_hdl = NewPixPat();
  590.         saved_bk_pp_hdl = ((CGrafPtr)wp)->bkPixPat;
  591.         saved_pn_pp_hdl = ((CGrafPtr)wp)->pnPixPat;
  592.         saved_fill_pp_hdl = ((CGrafPtr)wp)->fillPixPat;
  593.         ((CGrafPtr)wp)->bkPixPat = dummy_bk_pp_hdl;
  594.         ((CGrafPtr)wp)->pnPixPat = dummy_pn_pp_hdl;
  595.         ((CGrafPtr)wp)->fillPixPat = dummy_fill_pp_hdl;
  596.             //    PenPat changes members of pnPixPat structure if current GrafPort
  597.             //    is color GrafPort.
  598.             //    If current GrafPort is color only, use CopyPixPat.
  599.     }
  600.     else {
  601.         copy_pattern(wp->pnPat, saved_pn_pat);
  602.         copy_pattern(wp->bkPat, saved_bk_pat);
  603.         copy_pattern(wp->fillPat, saved_fill_pat);
  604.     }
  605.     saved_pn_mode = wp->pnMode;
  606.     saved_pn_size = wp->pnSize;
  607.         //    I used to use GetPenState. But I feel that GetPenState offen
  608.         //    work properly. So I copy pnSize and pnMode direct.
  609.  
  610.     SetPort(wp);
  611.     mp_g = mp;
  612.  
  613.     new_rgn            = NewRgn();
  614.     saved_vis_rgn    = NewRgn();
  615.     saved_clip_rgn    = NewRgn();
  616.         //    vis & clipRgn seem not to be changed if you change without using system
  617.         //  routines like SetClip. Especially visRgn (it has no system routine).
  618.     
  619.     marquee_rgn_spread_l = NewRgn();
  620.     
  621.     CopyRgn(wp->visRgn,        saved_vis_rgn);        //    Don't forget NewRgn before CopyRgn!
  622.     CopyRgn(wp->clipRgn,    saved_clip_rgn);
  623.     
  624.     saved_pt_g.h = wp->portRect.right;
  625.     saved_pt_g.v = wp->portRect.bottom;
  626.     LocalToGlobal(&saved_pt_g);
  627.     saved_rect_g.right    = saved_pt_g.h;
  628.     saved_rect_g.bottom    = saved_pt_g.v;
  629.     saved_pt_g.h = wp->portRect.left;
  630.     saved_pt_g.v = wp->portRect.top;
  631.     LocalToGlobal(&saved_pt_g);
  632.     saved_rect_g.left    = saved_pt_g.h;
  633.     saved_rect_g.top    = saved_pt_g.v;
  634.         //    'g' in 'saved_rect_g' etc. mean global coordinates.
  635.         //    'saved_pt_g' shows the top-left corner of portRect.
  636.     
  637.     offset.h    = mp_g.h - saved_pt_g.h;    
  638.     offset.v    = mp_g.v - saved_pt_g.v;    
  639.         //    'offset's are differences between the coordinates of
  640.         //    mouse point and top-left of portRect. Normally plus.
  641.     
  642.     c_rect_g    = (**((WindowPeek)wp)->contRgn).rgnBBox;
  643.     s_rgn_g        = ((WindowPeek)wp)->strucRgn;
  644.     s_rect_g    = (**s_rgn_g).rgnBBox;
  645.     
  646.     gap.left    = saved_rect_g.left    - s_rect_g.left;                                    
  647.     gap.top        = saved_rect_g.top    - s_rect_g.top;                                    
  648.     gap.right    = s_rect_g.right    - saved_rect_g.right;
  649.     gap.bottom    = s_rect_g.bottom    - saved_rect_g.bottom;
  650.         //    These 'gap's are differences between portRect and
  651.         //    structure rectangle. These are also plus.
  652.     
  653.     c_width        = saved_rect_g.right    - saved_rect_g.left;
  654.     c_height    = saved_rect_g.bottom    - saved_rect_g.top;
  655.     screen_width    = gray_rect.right    - gray_rect.left;
  656.     screen_height    = gray_rect.bottom    - gray_rect.top    - menu_bar_height;
  657.     
  658.     PortSize(screen_width, screen_height);
  659.         //    Spread current grafport to draw the marquee.
  660.     
  661.     MovePortTo(gray_rect.left, gray_rect.top + menu_bar_height);
  662. //    PortChanged((GrafPtr)wp);
  663.     RectRgn(new_rgn, &(wp->portRect));
  664.     UnionRgn(new_rgn, wp->visRgn,    wp->visRgn);
  665.     UnionRgn(new_rgn, wp->clipRgn,    wp->clipRgn);
  666.     DisposeRgn(new_rgn);
  667. //    PortChanged((GrafPtr)wp);
  668.     SetPort(wp);
  669.         //    vis & clipRgn are setted here.
  670.         //    PortChanged is sometimes unimplemented (especially old Mac).
  671.         //    So you had better to use SetPort if you want to change property of grafport
  672.         //    without use of system routines.
  673.     
  674.     p.h = s_rect_g.left;
  675.     p.v = s_rect_g.top;
  676.     GlobalToLocal(&p);
  677.     spread_l_to_g.h = s_rect_g.left    - p.h;
  678.     spread_l_to_g.v = s_rect_g.top    - p.v;
  679.         //    These 'spread_l_to_g's are differences between 
  680.         //    'spreaded' local coordinates and global.
  681.         //    Adding spread_l_to_g converts suspended local coordinates to global.
  682.         //    And substracting spread_l_to_g converts global to suspended local.
  683.     
  684.     r_g = *r;
  685.     work_r = gray_rect;
  686.     work_r.top += menu_bar_height + 2;
  687.     SectRect(&r_g, &work_r, &r_g);
  688.     
  689.     CopyRgn(s_rgn_g, marquee_rgn_spread_l);
  690.     OffsetRgn(marquee_rgn_spread_l, - spread_l_to_g.h, - spread_l_to_g.v);
  691.         //    Rgn is prepared as Handle. So "marquee_rgn = s_rgn" is wrong if you don't
  692.         //    want to touch original strucRgn.
  693.         //    And move the marquee to the proper spreaded local point.
  694.     
  695.     PenSize(1,1);
  696.     PenMode(patXor);
  697.     PenPat(my_qd_globals.gray);
  698.     
  699.     FrameRgn(marquee_rgn_spread_l);
  700.     
  701.     old_pt_g = mp_g;
  702.     
  703.     w_g.h = saved_rect_g.left;
  704.     w_g.v = saved_rect_g.top;
  705.     
  706.     while(StillDown()) {
  707.         GetMouse(&new_pt_g);
  708.         LocalToGlobal(&new_pt_g);
  709.         if(PtInRect(new_pt_g, &r_g)) {
  710.             if    (!EqualPt(new_pt_g,    old_pt_g))    {
  711.                 w_g.h = new_pt_g.h - offset.h;
  712.                 w_g.v = new_pt_g.v - offset.v;
  713.                 h_changed = v_changed = false;
  714.                 wpk = (WindowPeek)FrontWindow();
  715.                 while(wpk) {
  716.                     if(wpk != (WindowPeek)wp) {
  717.                         wpk_rect_g = (**wpk->strucRgn).rgnBBox;
  718.                         if(!h_changed &&(abs(wpk_rect_g.left
  719.                                 - (w_g.h - gap.left)) <= 5))    {
  720.                             w_g.h = wpk_rect_g.left + gap.left;
  721.                             h_changed = true;
  722.                         }
  723.                         if(!h_changed &&(abs(wpk_rect_g.right
  724.                                 - (w_g.h - gap.left)) <= 5)) {
  725.                             w_g.h = wpk_rect_g.right + gap.left;
  726.                             h_changed = true;
  727.                         }
  728.                         if(!h_changed &&(abs(wpk_rect_g.left
  729.                                 - (w_g.h + c_width + gap.right)) <= 5)) {
  730.                             w_g.h = wpk_rect_g.left - c_width - gap.right;
  731.                             h_changed = true;
  732.                         }
  733.                         if(!h_changed &&(abs(wpk_rect_g.right
  734.                                 - (w_g.h + c_width + gap.right)) <= 5)) {
  735.                             w_g.h = wpk_rect_g.right - c_width - gap.right;
  736.                             h_changed = true;
  737.                         }
  738.                         if(!v_changed &&(abs(wpk_rect_g.top
  739.                                 - (w_g.v - gap.top)) <= 5)) {
  740.                             w_g.v = wpk_rect_g.top + gap.top;
  741.                             v_changed = true;
  742.                         }
  743.                         if(!v_changed &&(abs(wpk_rect_g.bottom
  744.                                 - (w_g.v - gap.top)) <= 5)) {
  745.                             w_g.v = wpk_rect_g.bottom + gap.top;
  746.                             v_changed = true;
  747.                         }
  748.                         if(!v_changed &&(abs(wpk_rect_g.top
  749.                             - (w_g.v + c_height + gap.bottom)) <= 5)) {
  750.                             w_g.v = wpk_rect_g.top - c_height - gap.bottom;
  751.                             v_changed = true;
  752.                         }
  753.                         if(!v_changed &&(abs(wpk_rect_g.bottom
  754.                             - (w_g.v + c_height + gap.bottom)) <= 5)) {
  755.                             w_g.v = wpk_rect_g.bottom - c_height- gap.bottom;
  756.                             v_changed = true;
  757.                         }
  758.                         wpk    = wpk->nextWindow;
  759.                         if(h_changed && v_changed)        wpk = (WindowPeek)0;
  760.                     }
  761.                     else {
  762.                         wpk = wpk->nextWindow;
  763.                     }
  764.                     
  765.                 }
  766.                 FrameRgn(marquee_rgn_spread_l);
  767.             
  768.                 OffsetRgn(marquee_rgn_spread_l,
  769.                     w_g.h - gap.left    - spread_l_to_g.h
  770.                                 - (**marquee_rgn_spread_l).rgnBBox.left,
  771.                     w_g.v - gap.top        - spread_l_to_g.v
  772.                                 - (**marquee_rgn_spread_l).rgnBBox.top);
  773.                         //    'w_g's show top-left corner of portRect.
  774.                         //    And portRect has local coordinates.
  775.                                 
  776.                 FrameRgn(marquee_rgn_spread_l);
  777.                 old_pt_g = new_pt_g;
  778.             }
  779.         }    
  780.     }
  781.     FrameRgn(marquee_rgn_spread_l);
  782.     PortSize(saved_rect_g.right        - saved_rect_g.left,
  783.              saved_rect_g.bottom    - saved_rect_g.top);
  784.     MovePortTo(saved_pt_g.h, saved_pt_g.v);
  785.     CopyRgn(saved_vis_rgn,        wp->visRgn);
  786.     CopyRgn(saved_clip_rgn,        wp->clipRgn);
  787. //    PortChanged((GrafPtr)wp);
  788.     MoveWindow(wp, w_g.h, w_g.v, false);
  789.     DisposeRgn(marquee_rgn_spread_l);
  790.     DisposeRgn(saved_vis_rgn);
  791.     DisposeRgn(saved_clip_rgn);    //    Don't forget DisposeRgn!
  792.     SetPort(wp);
  793.     SetPort(saved_port);
  794.  
  795.     if(color_qd) {
  796.         RGBForeColor(&fore_color);
  797.         RGBBackColor(&back_color);
  798.         ((CGrafPtr)wp)->bkPixPat = saved_bk_pp_hdl;
  799.         ((CGrafPtr)wp)->pnPixPat = saved_pn_pp_hdl;
  800.         ((CGrafPtr)wp)->fillPixPat = saved_fill_pp_hdl;
  801.         DisposePixPat(dummy_bk_pp_hdl);
  802.         DisposePixPat(dummy_pn_pp_hdl);
  803.         DisposePixPat(dummy_fill_pp_hdl);
  804.     }
  805.     else {
  806.         copy_pattern(saved_bk_pat, wp->bkPat);
  807.         copy_pattern(saved_fill_pat, wp->fillPat);
  808.         copy_pattern(saved_pn_pat, wp->pnPat);
  809.     }
  810.     wp->pnSize = saved_pn_size;
  811.     wp->pnMode = saved_pn_mode;
  812. }
  813.  
  814. void copy_pattern(Pattern src_pat, Pattern dst_pat)
  815. {
  816.     int        i;
  817.     
  818.     for(i = 0; i <= 7; i++) {
  819.         dst_pat[i] = src_pat[i];
  820.     }
  821. }
  822.  
  823. pascal void call_no_marquee_drag(WindowPtr wp, Point mp, Rect *r)
  824. {
  825.     GrafPtr     saved_port;
  826.     Point        old_pt, new_pt;
  827.     short        offset_h, offset_v;
  828.     WindowPeek    wpk;
  829.     Boolean        h_changed, v_changed;
  830.     Rect        wpk_rect;
  831.     short        w_width, w_height;
  832.     short        w_left, w_top;
  833.     short        gap_left, gap_top, gap_right, gap_bottom;
  834.     
  835.     GetPort(&saved_port);
  836.     SetPort(wp);
  837.     offset_h = mp.h - (**((WindowPeek)wp)->contRgn).rgnBBox.left;
  838.     offset_v = mp.v - (**((WindowPeek)wp)->contRgn).rgnBBox.top;
  839.     gap_left   = (**((WindowPeek)wp)->contRgn).rgnBBox.left    - (**((WindowPeek)wp)->strucRgn).rgnBBox.left;
  840.     gap_top    = (**((WindowPeek)wp)->contRgn).rgnBBox.top     - (**((WindowPeek)wp)->strucRgn).rgnBBox.top;
  841.     gap_right  = (**((WindowPeek)wp)->strucRgn).rgnBBox.right  - (**((WindowPeek)wp)->contRgn).rgnBBox.right;
  842.     gap_bottom = (**((WindowPeek)wp)->strucRgn).rgnBBox.bottom - (**((WindowPeek)wp)->contRgn).rgnBBox.bottom;
  843.     w_width = (**((WindowPeek)wp)->contRgn).rgnBBox.right
  844.             - (**((WindowPeek)wp)->contRgn).rgnBBox.left;
  845.     w_height = (**((WindowPeek)wp)->contRgn).rgnBBox.bottom
  846.             - (**((WindowPeek)wp)->contRgn).rgnBBox.top;
  847.     old_pt = mp;
  848.     while (StillDown()) {
  849.         GetMouse(&new_pt);
  850.         LocalToGlobal(&new_pt);
  851.         if (PtInRect(new_pt, r)) {
  852.             if (!EqualPt(new_pt, old_pt)) {
  853.                 w_left = new_pt.h - offset_h;
  854.                 w_top  = new_pt.v - offset_v;
  855.                 h_changed = v_changed = false;
  856.  
  857.                 wpk = (WindowPeek)FrontWindow();
  858.                 while(wpk)    {
  859.                     if(wpk != (WindowPeek)wp) {
  860.                         wpk_rect = (**wpk->strucRgn).rgnBBox;
  861.                         if (!h_changed &&(abs(wpk_rect.left - (w_left - gap_left)) <= 5)) {
  862.                             w_left = wpk_rect.left + gap_left;
  863.                             h_changed = true;
  864.                         }
  865.                         if (!h_changed &&(abs(wpk_rect.right - (w_left - gap_left)) <= 5)) {
  866.                             w_left = wpk_rect.right + gap_left;
  867.                             h_changed = true;
  868.                         }
  869.                         if (!h_changed &&(abs(wpk_rect.left - (w_left + w_width + gap_right)) <= 5)) {
  870.                             w_left = wpk_rect.left - w_width - gap_right;
  871.                             h_changed = true;
  872.                         }
  873.                         if (!h_changed &&(abs(wpk_rect.right - (w_left + w_width + gap_right)) <= 5)) {
  874.                             w_left = wpk_rect.right - w_width - gap_right;
  875.                             h_changed = true;
  876.                         }
  877.                         if (!v_changed &&(abs(wpk_rect.top - (w_top - gap_top)) <= 5)) {
  878.                             w_top = wpk_rect.top + gap_top;
  879.                             v_changed = true;
  880.                         }
  881.                         if (!v_changed &&(abs(wpk_rect.bottom - (w_top - gap_top)) <= 5)) {
  882.                             w_top = wpk_rect.bottom + gap_top;
  883.                             v_changed = true;
  884.                         }
  885.                         if (!v_changed &&(abs(wpk_rect.top - (w_top + w_height + gap_bottom)) <= 5)) {
  886.                             w_top = wpk_rect.top - w_height - gap_bottom;
  887.                             v_changed = true;
  888.                         }
  889.                         if (!v_changed &&(abs(wpk_rect.bottom - (w_top + w_height + gap_bottom)) <= 5)) {
  890.                             w_top = wpk_rect.bottom - w_height - gap_bottom;
  891.                             v_changed = true;
  892.                         }
  893.                         wpk = wpk->nextWindow;
  894.                         if(h_changed && v_changed)    wpk = (WindowPeek)0;
  895.                     } else {
  896.                         wpk = wpk->nextWindow;
  897.                     }
  898.                 }
  899.             
  900.                 MoveWindow(wp, w_left, w_top, false);
  901.                 old_pt = new_pt;
  902.             }
  903.         }
  904.     }
  905.     SetPort(saved_port);
  906. }
  907.  
  908.  
  909. pascal long call_custom_grow(WindowPtr wp, Point mp, Rect *r)
  910. {
  911.     GrafPtr            saved_port;
  912.     Point            old_pt_g, new_pt_g, p, spread_l_to_g, saved_pt_g, mp_g, offset,
  913.                     w_g, old_l_to_g, saved_pn_size;
  914.     WindowPeek        wpk;
  915.     Boolean            h_changed, v_changed, color_qd;
  916.     KeyMap            my_keymap;
  917.     Rect            wpk_rect_g, saved_rect_g, marquee_spread_l, c_rect_g, s_rect_g,
  918.                     gap, r_g;
  919.     short            c_width, c_height, screen_width, screen_height;
  920.     long            return_value = 0;
  921.     PenState        saved_pen_state;
  922.     RGBColor        fore_color, back_color;
  923.     long            l;
  924.     RgnHandle        new_rgn, saved_vis_rgn, saved_clip_rgn;
  925.     PixPatHandle    saved_pn_pp_hdl, saved_fill_pp_hdl, saved_bk_pp_hdl,
  926.                     dummy_pn_pp_hdl, dummy_fill_pp_hdl, dummy_bk_pp_hdl;
  927.     Pattern            saved_bk_pat, saved_fill_pat, saved_pn_pat;
  928.     short            saved_pn_mode;
  929.         
  930.     GetPort(&saved_port);
  931.     if(color_qd = TrapAvailable(_GetForeColor)) {
  932.         GetForeColor(&fore_color);
  933.         GetBackColor(&back_color);
  934.         dummy_bk_pp_hdl = NewPixPat();
  935.         dummy_pn_pp_hdl = NewPixPat();
  936.         dummy_fill_pp_hdl = NewPixPat();
  937.         saved_bk_pp_hdl = ((CGrafPtr)wp)->bkPixPat;
  938.         saved_pn_pp_hdl = ((CGrafPtr)wp)->pnPixPat;
  939.         saved_fill_pp_hdl = ((CGrafPtr)wp)->fillPixPat;
  940.         ((CGrafPtr)wp)->bkPixPat = dummy_bk_pp_hdl;
  941.         ((CGrafPtr)wp)->pnPixPat = dummy_pn_pp_hdl;
  942.         ((CGrafPtr)wp)->fillPixPat = dummy_fill_pp_hdl;
  943.     }
  944.     else {
  945.         copy_pattern(wp->pnPat, saved_pn_pat);
  946.         copy_pattern(wp->bkPat, saved_bk_pat);
  947.         copy_pattern(wp->fillPat, saved_fill_pat);
  948.     }
  949.     saved_pn_mode = wp->pnMode;
  950.     saved_pn_size = wp->pnSize;
  951.     
  952.     SetPort(wp);
  953.     mp_g = mp;
  954.     
  955.     old_l_to_g.h = wp->portRect.left;
  956.     old_l_to_g.v = wp->portRect.top;
  957.     LocalToGlobal(&old_l_to_g);
  958.         //    Adding old_l_to_g converts old (not spreaded) local coordinates to global.
  959.     
  960.     r_g = *r;
  961.         //    r shows the restrict "size" here.
  962.     
  963.     if(r_g.right > gray_rect.right)
  964.         r_g.right  = gray_rect.right;
  965.             //    Set maximum window size(horizontal) to appropriate size.
  966.                     
  967.     if(r_g.bottom > gray_rect.bottom)
  968.         r_g.bottom = gray_rect.bottom;
  969.             //    Set maximum window size(vertical) to appropriate size.
  970.             
  971.     OffsetRect(&r_g, old_l_to_g.h, old_l_to_g.v);
  972.         //    Here, r shows the restrict rectangle (coordinations).
  973.     
  974.     new_rgn = NewRgn();
  975.     saved_vis_rgn    = NewRgn();
  976.     saved_clip_rgn    = NewRgn();
  977.     
  978.     CopyRgn(wp->visRgn,        saved_vis_rgn);
  979.     CopyRgn(wp->clipRgn,    saved_clip_rgn);
  980.     
  981.     saved_pt_g.h = wp->portRect.right;
  982.     saved_pt_g.v = wp->portRect.bottom;
  983.     LocalToGlobal(&saved_pt_g);
  984.     saved_rect_g.right    = saved_pt_g.h;
  985.     saved_rect_g.bottom    = saved_pt_g.v;
  986.     saved_pt_g.h = wp->portRect.left;
  987.     saved_pt_g.v = wp->portRect.top;
  988.     LocalToGlobal(&saved_pt_g);
  989.     saved_rect_g.left    = saved_pt_g.h;
  990.     saved_rect_g.top    = saved_pt_g.v;
  991.     
  992.     offset.h = saved_rect_g.right    - mp.h;
  993.     offset.v = saved_rect_g.bottom    - mp.v;
  994.     
  995.     c_rect_g    = (**((WindowPeek)wp)->contRgn).rgnBBox;
  996.     s_rect_g    = (**((WindowPeek)wp)->strucRgn).rgnBBox;
  997.     
  998.     gap.left    = saved_rect_g.left    - s_rect_g.left;
  999.     gap.top        = saved_rect_g.top    - s_rect_g.top;
  1000.     gap.right    = s_rect_g.right        - saved_rect_g.right;
  1001.     gap.bottom    = s_rect_g.bottom        - saved_rect_g.bottom;
  1002.     
  1003.     c_width        = saved_rect_g.right    - saved_rect_g.left;
  1004.     c_height    = saved_rect_g.bottom    - saved_rect_g.top;
  1005.     screen_width    = gray_rect.right    - s_rect_g.left;
  1006.     screen_height    = gray_rect.bottom    - s_rect_g.top;
  1007.     
  1008.     PortSize(screen_width, screen_height);
  1009.     MovePortTo(s_rect_g.left, s_rect_g.top);
  1010. //    PortChanged((GrafPtr)wp);
  1011.     RectRgn(new_rgn, &(wp->portRect));
  1012.     UnionRgn(new_rgn, wp->visRgn,    wp->visRgn);
  1013.     UnionRgn(new_rgn, wp->clipRgn,    wp->clipRgn);
  1014.     DisposeRgn(new_rgn);
  1015. //    PortChanged((GrafPtr)wp);
  1016.     SetPort(wp);
  1017.     
  1018.     p.h = s_rect_g.left;
  1019.     p.v = s_rect_g.top;
  1020.     GlobalToLocal(&p);
  1021.     spread_l_to_g.h = s_rect_g.left    - p.h;
  1022.     spread_l_to_g.v = s_rect_g.top    - p.v;
  1023.     
  1024.     marquee_spread_l.left    = s_rect_g.left - spread_l_to_g.h;
  1025.     marquee_spread_l.top    = s_rect_g.top  - spread_l_to_g.v;
  1026.     marquee_spread_l.right    = s_rect_g.right    - spread_l_to_g.h + 1;
  1027.     marquee_spread_l.bottom    = s_rect_g.bottom    - spread_l_to_g.v + 1;
  1028.         //    '+ 1' is added because sysytem routine does so.
  1029.     
  1030.     PenSize(1,1);
  1031.     PenMode(patXor);
  1032.     PenPat(my_qd_globals.gray);
  1033.     
  1034.     draw_marquee(&marquee_spread_l, &gap);
  1035.     
  1036.     old_pt_g = mp_g;
  1037.     w_g.h = saved_rect_g.right;
  1038.     w_g.v = saved_rect_g.bottom;
  1039.     
  1040.     while(StillDown()) {
  1041.         GetMouse(&new_pt_g);
  1042.         new_pt_g.h += offset.h;
  1043.         new_pt_g.v += offset.v;
  1044.         LocalToGlobal(&new_pt_g);
  1045.         if(!PtInRect(new_pt_g, &r_g)) {
  1046.             //    This checks too small or too larger window size.
  1047.             
  1048.             l = PinRect(&r_g, new_pt_g);
  1049.             if(new_pt_g.v != HiWord(l))
  1050.                 new_pt_g.v = HiWord(l);
  1051.             if(new_pt_g.h != LoWord(l))
  1052.                 new_pt_g.h = LoWord(l);
  1053.         }
  1054.         if(!EqualPt(new_pt_g, old_pt_g)) {
  1055.             w_g.h = new_pt_g.h;
  1056.             w_g.v = new_pt_g.v;
  1057.             h_changed    = v_changed = false;
  1058.             GetKeys(my_keymap);
  1059.             if(BitTst(&my_keymap, OPTION_KEY)) {
  1060.                 // If option key is pressed, the window grows every 5 pixels.
  1061.                 
  1062.                 w_g.h = (w_g.h / 5) * 5;
  1063.                 w_g.v = (w_g.v / 5) * 5;
  1064.             }
  1065.             else {
  1066.                 wpk = (WindowPeek)FrontWindow();
  1067.                 while(wpk) {
  1068.                     if(wpk != (WindowPeek)wp) {
  1069.                         wpk_rect_g = (**wpk->strucRgn).rgnBBox;
  1070.                         if (!h_changed && (abs(wpk_rect_g.left
  1071.                                 - (w_g.h + gap.right)) <= 5)) {
  1072.                             w_g.h = wpk_rect_g.left - gap.right;
  1073.                             h_changed = true;
  1074.                         }
  1075.                         if(!h_changed && (abs(wpk_rect_g.right
  1076.                                 - (w_g.h + gap.right)) <= 5)) {
  1077.                             w_g.h = wpk_rect_g.right - gap.right;
  1078.                             h_changed = true;
  1079.                         }
  1080.                     
  1081.                         if(!v_changed && (abs(wpk_rect_g.top
  1082.                                 - (w_g.v + gap.bottom)) <= 5)) {
  1083.                             w_g.v = wpk_rect_g.top - gap.bottom;
  1084.                             v_changed = true;
  1085.                         }
  1086.                         if(!v_changed    && (abs(wpk_rect_g.bottom
  1087.                                 - (w_g.v    + gap.bottom)) <= 5)) {
  1088.                             w_g.v = wpk_rect_g.bottom - gap.bottom;
  1089.                             v_changed = true;
  1090.                         }
  1091.                     
  1092.                         wpk = wpk->nextWindow;
  1093.                         if(h_changed && v_changed)
  1094.                             wpk = (WindowPeek)0;
  1095.                     }
  1096.                     else {
  1097.                         wpk = wpk->nextWindow;
  1098.                     }
  1099.                 }
  1100.             }
  1101.             draw_marquee(&marquee_spread_l, &gap);
  1102.             
  1103.             marquee_spread_l.right    = w_g.h    + gap.right        - spread_l_to_g.h - 1;
  1104.             marquee_spread_l.bottom    = w_g.v    + gap.bottom    - spread_l_to_g.v - 1;
  1105.                 //    '- 1' is added because '+ 1' was added :-)
  1106.             
  1107.             draw_marquee(&marquee_spread_l, &gap);
  1108.             
  1109.             c_width        = w_g.h    - saved_rect_g.left;
  1110.             c_height    = w_g.v    - saved_rect_g.top;
  1111.             old_pt_g = new_pt_g;
  1112.         }
  1113.     }
  1114.     
  1115.     draw_marquee(&marquee_spread_l, &gap);
  1116.     
  1117.     PortSize(saved_rect_g.right        - saved_rect_g.left, 
  1118.              saved_rect_g.bottom    - saved_rect_g.top);
  1119.     MovePortTo(saved_pt_g.h, saved_pt_g.v);
  1120.     CopyRgn(saved_vis_rgn,        wp->visRgn);
  1121.     CopyRgn(saved_clip_rgn,        wp->clipRgn);
  1122. //    PortChanged((GrafPtr)wp);
  1123.     DisposeRgn(saved_vis_rgn);
  1124.     DisposeRgn(saved_clip_rgn);
  1125.     SetPort(wp);
  1126.     SetPort(saved_port);
  1127.     SetPenState(&saved_pen_state);
  1128.     if(color_qd) {
  1129.         RGBForeColor(&fore_color);
  1130.         RGBBackColor(&back_color);
  1131.         ((CGrafPtr)wp)->bkPixPat = saved_bk_pp_hdl;
  1132.         ((CGrafPtr)wp)->pnPixPat = saved_pn_pp_hdl;
  1133.         ((CGrafPtr)wp)->fillPixPat = saved_fill_pp_hdl;
  1134.         DisposePixPat(dummy_bk_pp_hdl);
  1135.         DisposePixPat(dummy_pn_pp_hdl);
  1136.         DisposePixPat(dummy_fill_pp_hdl);
  1137.     }
  1138.     else {
  1139.         copy_pattern(saved_pn_pat, wp->pnPat);
  1140.         copy_pattern(saved_bk_pat, wp->bkPat);
  1141.         copy_pattern(saved_fill_pat, wp->fillPat);
  1142.     }
  1143.     wp->pnSize = saved_pn_size;
  1144.     wp->pnMode = saved_pn_mode;
  1145.     
  1146.     if((mp.h != old_pt_g.h - offset.h) || (mp.v != old_pt_g.v - offset.v)) {
  1147.         return_value =        c_height;
  1148.         return_value <<=    16;
  1149.         return_value +=        c_width;
  1150.     }
  1151.     return(return_value);
  1152. }
  1153.  
  1154. void draw_marquee(Rect *marquee, Rect *gap)    
  1155.     //    This routine draws the complicated marquee used in call_custom_grow.
  1156. {
  1157.     FrameRect(marquee);
  1158.     MoveTo(marquee->left,    marquee->top + gap->top - 1);
  1159.     LineTo(marquee->right,    marquee->top + gap->top - 1);
  1160.     MoveTo(marquee->left,    marquee->bottom - 16);
  1161.     LineTo(marquee->right,    marquee->bottom - 16);
  1162.     MoveTo(marquee->right - 16, marquee->top + gap->top);
  1163.     LineTo(marquee->right - 16, marquee->bottom);
  1164.         //    16 means width of scroll bar.
  1165. }
  1166.  
  1167.  
  1168.